package com.tansun.easycare.rule.utils;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.kie.api.KieBase;
import org.kie.api.io.ResourceType;
import org.kie.api.runtime.KieSession;
import com.alibaba.fastjson.JSON;
import com.tansun.easycare.rule.common.model.RuleExecParam;
import com.tansun.easycare.rule.exception.BizException;
import com.tansun.easycare.rule.ruletest.model.RuleInputVO;
import com.tansun.easycare.rule.ruletest.model.RuleSingleTest;
import com.tansun.easycare.rule.ruleversion.entity.RuleVersioninfo;
import com.tansun.rule.common.KieBaseFactory;
import com.tansun.rule.common.ResourceContentInfo;
import com.tansun.rule.common.RuleModelTypeEnum;
import com.tansun.rule.listener.ExecuterProcessEventListener;
import com.tansun.rule.utils.DroolsRuleLog;
import com.tansun.rule.utils.MClass;
import com.tansun.rule.utils.RuleHelper;
import com.tansun.rule.utils.StringUtils;

public class DroolsExcuteDrlUtils {

    private DroolsRuleLog droolsRuleLog = new DroolsRuleLog(true);
    
    private  Map<String,String> drlMap  = new HashMap<String, String>();
    
    private  Map<String,String>  funcMap  = new HashMap<>();
    
    private  String   projectCode;


    /**
     * 执行单个文件,批量数据计算
     *
     * @param insertMap   入参
     * @param agendaGroup ruleFlowid
     */
    public RuleSingleTest excuteDrlFile(List<RuleInputVO>  inputList, Map<String, MClass> metaMap, String agendaGroup,KieBase kieBase) {
    	RuleSingleTest  ruleSingelTest = new  RuleSingleTest();  
    	ruleSingelTest.setInputList(inputList);
		RuleHelper ruleHelper = new RuleHelper(metaMap);
		ruleHelper.setProjectCode(this.projectCode);
   	    ruleHelper.setFuncDrl(this.funcMap.get(this.projectCode));
       	if (this.drlMap !=null ) {
       		 ruleHelper.setDrlMap(this.drlMap);
       	}

    	for (RuleInputVO inputVO : inputList) {
    		Date  bdate  = new  Date();
    		Map<String, Object>  map  =  inputVO.getInputMaps();
    		KieSession kieSession = kieBase.newKieSession();
    		try {
	           	ruleHelper.setInsertMap(map);
		        kieSession.setGlobal("ruleHelper", ruleHelper);
		        kieSession.setGlobal("metaMap", metaMap);
		        kieSession.setGlobal("dataMap", map);
		        droolsRuleLog.setRuleHelper(ruleHelper);
		        kieSession.setGlobal("droolsRuleLog", droolsRuleLog);
		        if (StringUtils.isNotBlank(agendaGroup)) {
		            kieSession.getAgenda().getAgendaGroup(agendaGroup).setFocus();
		        }
	            droolsRuleLog.setDataMap(map);
	            kieSession.insert(map);
	            kieSession.fireAllRules();
	            Date  edate  = new  Date();
	            inputVO.setExecTime(edate.getTime()-bdate.getTime());
    		}finally {
				kieSession.setGlobal("droolsRuleLog", null);
				kieSession.delete(kieSession.getFactHandle(map));	//清空对象
	            kieSession.dispose();
    		}
        }
        return  ruleSingelTest;
    }
    
    public void  excuteDrlFile(Map<String, Object> insertMap, List<RuleExecParam>  execList, Map<String, MClass> metaMap) {
        List<ResourceContentInfo> list  = new  ArrayList<>();
        if (this.projectCode !=null) {
       	   String  funDrl =this.funcMap.get(projectCode);
       	   if (funDrl != null) {
       		  list.add(new ResourceContentInfo(funDrl, ResourceType.DRL));
       	   }
       }
       if (execList != null) {
    	   for (RuleExecParam execParam:execList) {
    		   list.add(new ResourceContentInfo(execParam.getRuleContent(), ResourceType.DRL));
    	   }
       }
       KieBase  kieBase =  KieBaseFactory.getInstance().createKieBase(list);
       for (RuleExecParam param: execList) {
    		Date  bdate  = new  Date();
    		KieSession kieSession = kieBase.newKieSession();
    		try {
	    		RuleHelper ruleHelper = new RuleHelper(metaMap);
	           	ruleHelper.setInsertMap(insertMap);
		        kieSession.setGlobal("ruleHelper", ruleHelper);
		        kieSession.setGlobal("metaMap", metaMap);
		        kieSession.setGlobal("dataMap", insertMap);
		        droolsRuleLog.setRuleHelper(ruleHelper);
		        kieSession.setGlobal("droolsRuleLog", droolsRuleLog);
		        if (StringUtils.isNotBlank(param.getCode())) {
		            kieSession.getAgenda().getAgendaGroup(param.getCode()).setFocus();
		        }
	            droolsRuleLog.setDataMap(insertMap);
	            kieSession.insert(insertMap);
	            kieSession.fireAllRules();
	            Date  edate  = new  Date();
	            param.setExecTime(edate.getTime()-bdate.getTime());
    		}finally {
	            kieSession.delete(kieSession.getFactHandle(insertMap));
	            kieSession.dispose();
    		}

        }
        //printDroolsRuleLog(droolsRuleLog);
    }


    /**
     * 执行drl
     *
     * @param insertMap      入参
     * @param contentDrl     drl信息
     * @param bomMappingPath 数据模型的路径
     * @param agendaGroup    ruleFlowid
     */
    public void excuteDrlFile(Map<String, Object> insertMap, String contentDrl, Map<String, MClass> metaMap, String agendaGroup) {

        if (contentDrl == null) {
            throw new RuntimeException("drl文件不存在！");
        }
        
        KieBase kieBase = KieBaseFactory.getInstance().createKieBase(contentDrl, ResourceType.DRL);
        KieSession kieSession = kieBase.newKieSession();
        kieSession.insert(insertMap);
        if (StringUtils.isNotBlank(agendaGroup)) {
            kieSession.getAgenda().getAgendaGroup(agendaGroup).setFocus();
        }
        RuleHelper ruleHelper = new RuleHelper(metaMap);
        droolsRuleLog.setRuleHelper(ruleHelper);
        droolsRuleLog.setDataMap(insertMap);
        kieSession.setGlobal("ruleHelper", ruleHelper);
        kieSession.setGlobal("droolsRuleLog", droolsRuleLog);
        kieSession.setGlobal("metaMap", metaMap);
        kieSession.setGlobal("dataMap", insertMap);
        kieSession.fireAllRules();
        printDroolsRuleLog(droolsRuleLog);
    }

    public void excuteDrl(Map<String, Object> insertMap, String[] contentDrl, Map<String, MClass> metaMap, String agendaGroup, String[] bpmnContent) {
        KieSession kieSession =null;
        List<ResourceContentInfo>  list  = new  ArrayList<>();
        ResourceContentInfo  drlContent  = null;
        for (String drl : contentDrl) {
        	if(drl.indexOf("JPMML-SkLearn")>-1)
        		continue;
        	 drlContent = new ResourceContentInfo(drl, ResourceType.DRL);
        	 list.add(drlContent);
        }
        if (bpmnContent != null) {
            for (String bpmnStr : bpmnContent) {
            	 drlContent = new ResourceContentInfo(bpmnStr, ResourceType.BPMN2);
            	 list.add(drlContent);
            }
        }
        String  funcStr =this.funcMap.get(this.projectCode); 
        try {
        	KieBase kieBase  = KieBaseFactory.getInstance().createKieBase(list);
	        kieSession = kieBase.newKieSession();
	        kieSession.insert(insertMap);
	        RuleHelper ruleHelper = new RuleHelper(metaMap,insertMap,this.drlMap);
	        ruleHelper.setFuncDrl(funcStr);
	        ruleHelper.setProjectCode(projectCode);
	        droolsRuleLog.setRuleHelper(ruleHelper);
	        droolsRuleLog.setDataMap(insertMap);
	        kieSession.setGlobal("ruleHelper", ruleHelper);
	        kieSession.setGlobal("droolsRuleLog", droolsRuleLog);
	        kieSession.setGlobal("metaMap", (Map)metaMap);
	        kieSession.setGlobal("dataMap", (Map)insertMap);
	        ExecuterProcessEventListener listener = new ExecuterProcessEventListener();
	        kieSession.addEventListener(listener);
	        if (!StringUtils.isEmpty(agendaGroup)) {
	            if (bpmnContent != null && bpmnContent.length > 0) {
	                kieSession.startProcess(agendaGroup);
	            } else {
	                kieSession.getAgenda().getAgendaGroup(agendaGroup).setFocus();
	            }
	        }
	        kieSession.fireAllRules();
	        printDroolsRuleLog(droolsRuleLog);
        }catch (Exception e) {
        	e.printStackTrace();
        	throw new BizException(e, e.getMessage());
		} finally {
        	if (kieSession != null) {
        	    kieSession.delete(kieSession.getFactHandle(insertMap));
        		kieSession.dispose();
        	}  
        }
    }    

    
    
    public void executeDrlContents(Map<String, Object> insertMap, List<RuleVersioninfo> flowVersions, Map<String, MClass> metaMap, String agendaGroup) throws Exception {
        String context = null;
        List<String>  drlList= new ArrayList<String>();
        List<String>  bpmnList= new ArrayList<String>();
        for (RuleVersioninfo versioninfo : flowVersions) {
            if (versioninfo.getModelType().equals(RuleModelTypeEnum.DataComponet.getCode()))
                continue;
            context = versioninfo.getRuleContent();
            if (versioninfo.getModelType().equals(RuleModelTypeEnum.RuleFlow.code)
            		||versioninfo.getModelType().equals(RuleModelTypeEnum.StrategyFlow.code)
            		||versioninfo.getModelType().equals(RuleModelTypeEnum.ExecutionBlock.code)
            		||versioninfo.getModelType().equals(RuleModelTypeEnum.CodeBlock.code)) {
                bpmnList.add(context);
            } else {
                drlList.add(context);
            }
        }
        String[]  drlArgs  = new String[drlList.size()];
        drlList.toArray(drlArgs);
        String[]  bmpArgs  = new String[bpmnList.size()];
        bpmnList.toArray(bmpArgs);
        this.excuteDrl(insertMap, drlArgs, metaMap, agendaGroup, bmpArgs);
    }    

   
   private  RuleHelper  buildHelper( Map<String, MClass> metaMap,DroolsRuleLog  droolsRuleLog) {
       RuleHelper ruleHelper = new RuleHelper(metaMap);
       if (this.projectCode !=null) {
       	 ruleHelper.setFuncDrl(this.funcMap.get(this.projectCode));
       	 if (this.drlMap !=null ) {
       		 ruleHelper.setDrlMap(this.drlMap);
       	 }
       	 ruleHelper.setProjectCode(this.projectCode);
       }
       ruleHelper.setDroolsRuleLog(droolsRuleLog);
       return  ruleHelper;
   }
    
    

    public RuleSingleTest excuteBatchDrl(List<RuleInputVO>  inputList ,  Map<String, MClass> metaMap, String agendaGroup,KieBase  kieBase,boolean isBpmn) {
    	RuleSingleTest  ruleSingleTest = new  RuleSingleTest();  
    	ruleSingleTest.setInputList(inputList);
    	RuleHelper ruleHelper  = null;
        KieSession kieSession =null;
        droolsRuleLog  = new  DroolsRuleLog(true);
    	ruleHelper = this.buildHelper(metaMap,droolsRuleLog);
        for (RuleInputVO inputVO : inputList) {
        	Map<String, Object>   map  =  inputVO.getInputMaps();
         	try {
         		
        		droolsRuleLog.setRuleHelper(ruleHelper);
                kieSession = kieBase.newKieSession();
                kieSession.setGlobal("ruleHelper", ruleHelper);
                kieSession.setGlobal("droolsRuleLog", droolsRuleLog);
                kieSession.setGlobal("metaMap", metaMap);
	            droolsRuleLog.setDataMap(map);
	            Date  bdate = new  Date();
	            ruleHelper.setInsertMap(map);
	            kieSession.setGlobal("dataMap", map);
	            kieSession.insert(map);
	            if (StringUtils.isNotBlank(agendaGroup)) {
	                if (isBpmn) {
	                    kieSession.startProcess(agendaGroup);
	                } else
	                    kieSession.getAgenda().getAgendaGroup(agendaGroup).setFocus();
	            }
	            kieSession.fireAllRules();
	            Date  edate  = new  Date();
	            inputVO.setExecTime((edate.getTime()-bdate.getTime()));
        	}catch (Exception e) {
        		inputVO.setExecTime(null);
        		e.printStackTrace();
			}finally {
				kieSession.delete(kieSession.getFactHandle(map));
		        kieSession.dispose();
			}
        }
        //printDroolsRuleLog(droolsRuleLog);
        return  ruleSingleTest;
        //System.gc();

    }

 
    // 打印日志信息
    public static void printDroolsRuleLog(DroolsRuleLog droolsRuleLog) {
        List<Map<String, Object>> list = droolsRuleLog.getLogs();
        for (Map<String, Object> map : list) {
            String logStr = map.get("type") + " : " + map.get("group") + " : " + map.get("name");

            for (int i = 0; i < 5; i++) {
                if (map.get("info" + i) != null) {
                    logStr = logStr + " : info" + i + " > " + map.get("info" + i);
                } else {
                    break;
                }

            }
            if("ruleFlow_node".equals(map.get("type"))) {
            	logStr += JSON.toJSONString(map.get("preDataMap")) + "==>" + JSON.toJSONString(map.get("nextDataMap"));
            }
            System.out.println(logStr);
        }
    }

    public DroolsRuleLog getDroolsRuleLog() {
        return droolsRuleLog;
    }

	public void setDrlMap(Map<String, String> drlMap) {
		this.drlMap = drlMap;
	}



	public void setFuncMap(Map<String, String> funcMap) {
		this.funcMap = funcMap;
	}

	public void setProjectCode(String projectCode) {
		this.projectCode = projectCode;
	}
    
	
	

}
